using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DnsService.Services;
using NLog;

namespace DnsService.IPC
{
    /// <summary>
    /// 基于 Named Pipes 的命令服务端，面向桌面UI进行IPC交互。
    /// 每次连接处理一个命令，返回文本结果（支持多行）。
    /// 协议：客户端发送一行命令文本，服务端返回结果文本，末尾追加"__END__"行作为结束标记。
    /// </summary>
    public sealed class NamedPipeCommandServer : IDisposable
    {
        public const string DefaultPipeName = "LocalDnsServicePipe";

        private readonly Logger _logger = LogManager.GetCurrentClassLogger();
        private readonly CommandExecutor _executor;
        private readonly string _pipeName;
        private CancellationTokenSource? _cts;
        private Task? _listenTask;

        public NamedPipeCommandServer(DnsService.Interfaces.IDnsService dnsService, DnsConfigManager configManager, string? pipeName = null)
        {
            if (dnsService == null) throw new ArgumentNullException(nameof(dnsService));
            if (configManager == null) throw new ArgumentNullException(nameof(configManager));
            _executor = new CommandExecutor(dnsService, configManager, CommandExecutor.CommandSource.UI);
            _pipeName = string.IsNullOrWhiteSpace(pipeName) ? DefaultPipeName : pipeName!;
        }

        /// <summary>
        /// 启动监听循环
        /// </summary>
        public void Start()
        {
            if (_listenTask != null && !_listenTask.IsCompleted) return;
            _cts = new CancellationTokenSource();
            _listenTask = Task.Run(() => ListenLoopAsync(_cts.Token));
            _logger.Info($"NamedPipeCommandServer 已启动，管道名: {_pipeName}");
        }

        /// <summary>
        /// 停止监听循环
        /// </summary>
        public void Stop()
        {
            try
            {
                _cts?.Cancel();
                _listenTask?.Wait(1000);
            }
            catch (Exception ex)
            {
                _logger.Warn(ex, "停止管道服务时出现异常");
            }
            finally
            {
                _cts?.Dispose();
                _cts = null;
                _listenTask = null;
                _logger.Info("NamedPipeCommandServer 已停止");
            }
        }

        private async Task ListenLoopAsync(CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                try
                {
                    using var server = new NamedPipeServerStream(
                        _pipeName,
                        PipeDirection.InOut,
                        maxNumberOfServerInstances: 1,
                        PipeTransmissionMode.Byte,
                        PipeOptions.Asynchronous);

                    _logger.Debug("等待管道连接...");
                    await server.WaitForConnectionAsync(token);
                    _logger.Debug("管道客户端已连接");

                    using var reader = new StreamReader(server, Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024, leaveOpen: true);
                    using var writer = new StreamWriter(server, Encoding.UTF8, bufferSize: 1024, leaveOpen: true) { AutoFlush = true };

                    // 连接确认（握手），提升客户端感知与可观测性
                    await writer.WriteLineAsync("CONNECTED");
                    _logger.Debug("已发送连接确认");

                    // 读取一行命令
                    _logger.Debug("开始读取命令");
                    string? commandLine = null;
                    try
                    {
                        var readTask = reader.ReadLineAsync();
                        var completed = await Task.WhenAny(readTask, Task.Delay(3000, token));
                        if (completed != readTask)
                        {
                            _logger.Warn("读取命令超时，断开连接并返回错误");
                            await writer.WriteLineAsync("ERROR: 读取命令超时");
                            await writer.WriteLineAsync("__END__");
                            try { server.Disconnect(); } catch { }
                            continue;
                        }
                        commandLine = await readTask;
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }

                    if (commandLine is null)
                    {
                        _logger.Warn("客户端已关闭连接，未发送命令");
                        await writer.WriteLineAsync("ERROR: 客户端未发送命令即关闭连接");
                        await writer.WriteLineAsync("__END__");
                        continue;
                    }
                    if (string.IsNullOrWhiteSpace(commandLine))
                    {
                        _logger.Warn("收到空命令，忽略");
                        await writer.WriteLineAsync("ERROR: 空命令");
                        await writer.WriteLineAsync("__END__");
                        continue;
                    }

                    _logger.Debug($"收到命令: {commandLine}");

                    try
                    {
                        bool ok = _executor.Execute(commandLine, out string result);
                        await writer.WriteLineAsync(result ?? string.Empty);
                        await writer.WriteLineAsync("__END__");
                        _logger.Debug($"命令执行完成: {(ok ? "OK" : "ERROR")}");
                    }
                    catch (Exception ex)
                    {
                        _logger.Error(ex, "执行管道命令发生异常");
                        await writer.WriteLineAsync($"ERROR: {ex.Message}");
                        await writer.WriteLineAsync("__END__");
                    }

                    // 连接在处理完一个命令后关闭，等待下一次连接
                }
                catch (OperationCanceledException)
                {
                    // 正常退出
                    _logger.Debug("管道客户端已关闭");
                    break;
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "管道服务器循环异常，继续下一轮");
                    await Task.Delay(200, token);
                }
            }
        }

        public void Dispose()
        {
            Stop();
        }
    }
}